package net.slteam.base.util;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.*;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;

/**
 * ClassName: SpringUtil
 * Description:
 * date: 5/13/21 11:34 AM
 *
 * @author calm
 * @since JDK 1.8
 */
@SuppressWarnings("unused")
@Component("baseSpringUtil")
public class SpringUtil implements ApplicationContextAware, EnvironmentAware, ApplicationListener {

    private static ApplicationContext context;

    private static Environment environment;

    private static AutowireCapableBeanFactory beanFactory;

    private static DefaultListableBeanFactory defaultListableBeanFactory;

    public static <T> T getBean(Class<T> c) {
        try {
            return context.getBean(c);
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> T getBean(String beanname, Class<T> c) {
        try {
            return context.getBean(beanname, c);
        } catch (Exception e) {
            return null;
        }
    }

    public static <T> T getBean(String beanname) {
        try {
            return (T) context.getBean(beanname);
        } catch (Exception e) {
            return null;
        }
    }

    public static Object getBeanForAnnotation(Class<? extends Annotation> a) {
        return context.getBeansWithAnnotation(a).values().toArray()[0];
    }

    public static boolean isTest() {
        return checkProfileActive("test");
    }

    public static boolean isProd() {
        return checkProfileActive("prod");
    }

    public static boolean checkProfileActive(String profile) {
        if (ArrayUtils.isNotEmpty(environment.getActiveProfiles())) {
            return ArrayUtils.contains(environment.getActiveProfiles(), profile);
        } else {
            return ArrayUtils.contains(environment.getDefaultProfiles(), profile);
        }
    }

    public static String getApplicationName() {
        return getProperty("spring.application.name");
    }

    public static String getProperty(String s) {
        return environment.getProperty(s);
    }

//    String[] springBootAppBeanName = applicationContext.getBeanNamesForAnnotation(org.springframework.boot.autoconfigure.SpringBootApplication.class);

    public static String getProperty(String s, String s1) {
        return environment.getProperty(s, s1);
    }

    public static <T> T getProperty(String s, Class<T> aClass) {
        return environment.getProperty(s, aClass);
    }

    public static <T> T getProperty(String s, Class<T> aClass, T t) {
        return environment.getProperty(s, aClass, t);
    }

    /**
     * 获取aop代理对象
     *
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) AopContext.currentProxy();
    }

    public static void registerBean(String name, Object object) {
        defaultListableBeanFactory.registerSingleton(name, object);
        beanFactory.autowireBean(name);
    }

    @Override
    public void setEnvironment(Environment environment) {
        SpringUtil.environment = environment;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
        init();
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            context = ((ContextRefreshedEvent) event).getApplicationContext();
            init();
        }
    }

    private void init() {
        beanFactory = context.getAutowireCapableBeanFactory();
        defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
    }

}
